/**
 * 指令，仅用于element-plus 中的 dialog 使用
 * 可基于窗口各种拖拽使用
 */
const drag = {
    mounted(el, binding) {
        if (binding.value) {
            handleElShow(el)
        }
    },
    updated(el, binding) {
        if (binding.value) {
            handleElShow(el)
        } else {
            handleElHide(el)
        }
    },
    beforeUnmount(el) {
        handleElHide(el)
    }
}

async function handleElShow(el) {
    // 防止时间太快，拿不到dom
    await myPromise()
    const dialog = el.querySelector('.el-dialog')
    if (!dialog) {
        return
    }
    const header = el.querySelector('.el-dialog__header')
    const dialogMask = el.querySelector('.el-overlay')
    dialogMask.style.cssText += 'overflow: hidden;'
    header.style.cursor = 'move'
    let dragStatus = false
    let data = {
        // 数据源，不变部分为：window信息、dialog信息、mouse初始值信息，可变部分为：拖拽坐标位移
        window: {
            // window信息
            width: 0,
            height: 0
        },
        dialog: {
            x: 0,
            y: 0,
            width: 0,
            height: 0,
            marginTop: ''
        }, // dialog信息
        mouse: {
            // 鼠标初始信息
            x: 0,
            y: 0
        },
        drag: {
            // 拖拽过程信息
            x: 0,
            y: 0
        }
    }
    // 所有的监听只为了修改data数据
    header.addEventListener('mousedown', mouseDown)
    document.addEventListener('mousemove', mouseMove)
    document.addEventListener('mouseup', mouseUp)
    window.addEventListener('resize', sizeChange)
    // 边界处理，防止拖动位置溢出
    function handlePosition() {
        if (data.mouse.x - data.drag.x >= data.dialog.x) {
            data.drag.x = data.mouse.x - data.dialog.x
        }
        if (data.drag.x - data.mouse.x >= data.window.width - (data.dialog.x + data.dialog.width)) {
            data.drag.x = data.mouse.x + data.window.width - data.dialog.x - data.dialog.width
        }
        if (data.mouse.y - data.drag.y >= data.dialog.y) {
            data.drag.y = data.mouse.y - data.dialog.y
        }
        if (data.drag.y - data.mouse.y >= data.window.height - (data.dialog.y + data.dialog.height)) {
            data.drag.y = data.mouse.y + data.window.height - data.dialog.y - data.dialog.height
        }
        setPosition()
    }
    // 根据data来设置拖动后的位置
    function setPosition() {
        let top = data.drag.y - data.mouse.y + data.dialog.y
        let left = data.drag.x - data.mouse.x + data.dialog.x
        dialog.style.cssText += `position: absolute; top: calc(${top}px - ${data.dialog.marginTop}); left: ${left}px;`
    }
    function mouseDown(e) {
        // 获取dialog目前的位置，坐标, 以及屏幕当前的宽高
        // 一切初始数据的获取应该放置于此，避免其他如：宽度修改等一系列的影响
        if (e.button !== 0) {
            return
        }
        data.window = {
            width: document.body.clientWidth,
            height: document.body.clientHeight
        }
        data.dialog = dialog.getBoundingClientRect()
        data.dialog.marginTop = window.getComputedStyle(dialog).marginTop
        data.mouse = {
            x: e.clientX,
            y: e.clientY
        }
        dragStatus = true
    }
    function mouseMove(e) {
        if (dragStatus) {
            data.drag = {
                x: e.clientX,
                y: e.clientY
            }
            dialogMask.style.userSelect = 'none'
            handlePosition()
        }
    }
    function mouseUp(e) {
        dialogMask.style.userSelect = 'auto'
        dragStatus = false
    }
    function sizeChange(e) {
        // dialog.style.cssText += 'position: static';
    }
    function myPromise() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve()
            }, 500)
        })
    }
    // 方便卸载使用
    el.__mouseDown__ = mouseDown
    el.__mouseUp__ = mouseUp
    el.__mouseMove__ = mouseMove
    el.__sizeChange__ = sizeChange
}

function handleElHide(el) {
    // 避免重复开销，卸载所有的监听
    // 解决问题：多次创建新的实例 =》 监听不取消 =》 同时存在多个无用的监听，导致页面卡顿
    document.removeEventListener('mousedown', el.__mouseDown__)
    document.removeEventListener('mousemove', el.__mouseMove__)
    document.removeEventListener('mouseup', el.__mouseUp__)
    window.removeEventListener('resize', el.__sizeChange__)
}

export default drag
